package com.aims.server.common.util;

import com.aims.server.entity.ExtAccountForm;
import com.aims.server.entity.ExtAccountItem;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.*;

/**
 * 企业或集团外常用账户信息表Word文档导出工具类
 * 根据makebill.jpg图片格式生成docx文档
 */
public class ExtAccountWordExporter {

    /**
     * 导出Word文档
     *
     * @param form 表单数据
     * @return 文档字节数组
     * @throws IOException IO异常
     */
    public static byte[] exportToWord(ExtAccountForm form) throws IOException {
        try (XWPFDocument document = new XWPFDocument();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {

            // 1. 创建标题
            createTitle(document);

            // 2. 创建集团总部基本信息表格
            createBasicInfoTable(document, form);

            // 3. 添加空行
            document.createParagraph();

            // 4. 创建企业或集团外账号信息表格
            createAccountInfoTable(document, form);

            // 5. 添加主申请账号银行印鉴和填表日期
            createFooterInfo(document);

            // 6. 添加填表说明
            createFormExplanation(document);

            // 写入输出流
            document.write(out);
            return out.toByteArray();
        }
    }

    /**
     * 创建标题
     */
    private static void createTitle(XWPFDocument document) {
        // 主标题：中国工商银行深圳市分行
        XWPFParagraph title1 = document.createParagraph();
        title1.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun run1 = title1.createRun();
        run1.setText("中国工商银行深圳市分行");
        run1.setFontFamily("宋体");
        run1.setFontSize(16);
        run1.setBold(true);

        // 副标题：企业网上银行——企业或集团外币常用账户信息表
        XWPFParagraph title2 = document.createParagraph();
        title2.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun run2 = title2.createRun();
        run2.setText("企业网上银行——企业或集团外币常用账户信息表");
        run2.setFontFamily("宋体");
        run2.setFontSize(14);
        run2.setBold(false);

        // 添加空行
        document.createParagraph();
    }

    /**
     * 创建集团总部基本信息表格
     */
    private static void createBasicInfoTable(XWPFDocument document, ExtAccountForm form) {
        // 创建表格标题
        XWPFParagraph titlePara = document.createParagraph();
        titlePara.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleRun = titlePara.createRun();
        titleRun.setText("集团总部基本信息");
        titleRun.setFontFamily("宋体");
        titleRun.setFontSize(12);
        titleRun.setBold(true);

        // 创建表格 (3行3列的复杂表格)
        XWPFTable table = document.createTable(3, 3);
        table.setWidth("100%");

        // 设置表格边框
        setTableBorders(table);

        // 第一行：企业名 | 企业名称值 (跨两列)
        XWPFTableRow row0 = table.getRow(0);
        setCellText(row0.getCell(0), "企业名", true);
        mergeCellsHorizontally(table, 0, 1, 2);
        setCellText(row0.getCell(1), form.getCompanyName(), false);

        // 第二行：主申请账号 | 账号值 | 开户行名称 | 开户行值
        XWPFTableRow row1 = table.getRow(1);
        setCellText(row1.getCell(0), "主申请账号", true);

        // 分割第二列为账号和开户行名称
        String cellText = form.getMainApplyingAccount() + " 开户行名称: " + form.getMainApplyingAccountBankName();
        mergeCellsHorizontally(table, 1, 1, 2);
        setCellText(row1.getCell(1), cellText, false);

        // 第三行：法定代表人(或负责人) | 值 | 联系人 | 值 | 联系电话 | 值
        XWPFTableRow row2 = table.getRow(2);
        setCellText(row2.getCell(0), "法定代表人(或负责人)", true);

        // 合并并设置值
        String row2Text = form.getLegalRepresentative() + " 联系人: " + form.getContactPerson() + " 联系电话: " + form.getContactPhone();
        mergeCellsHorizontally(table, 2, 1, 2);
        setCellText(row2.getCell(1), row2Text, false);
    }

    /**
     * 创建企业或集团外账号信息表格
     */
    private static void createAccountInfoTable(XWPFDocument document, ExtAccountForm form) {
        // 创建表格标题
        XWPFParagraph titlePara = document.createParagraph();
        titlePara.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleRun = titlePara.createRun();
        titleRun.setText("企业或集团外账号信息");
        titleRun.setFontFamily("宋体");
        titleRun.setFontSize(12);
        titleRun.setBold(true);

        List<ExtAccountItem> items = form.getItems();
        if (items == null || items.isEmpty()) {
            items = new ArrayList<>();
        }

        // 处理basePermissionCertIdName - 可能需要多行
        // 首先，统计每个账号需要多少行
        List<AccountRowData> rowDataList = prepareAccountRowData(items);

        // 创建表格：表头(2行) + 数据行
        int totalRows = 2 + rowDataList.size();
        XWPFTable table = document.createTable(totalRows, 7);
        table.setWidth("100%");

        // 设置表格边框
        setTableBorders(table);

        // 第一行表头：业务类型 | 户名 | 账号 | 开户行名称 | 开户行号 | 开户行所在地 | 基本权限证书ID名称
        XWPFTableRow headerRow1 = table.getRow(0);
        setCellText(headerRow1.getCell(0), "业务类型", true);
        setCellText(headerRow1.getCell(1), "户名", true);
        setCellText(headerRow1.getCell(2), "账号", true);
        setCellText(headerRow1.getCell(3), "开户行名称", true);
        setCellText(headerRow1.getCell(4), "开户行号", true);
        setCellText(headerRow1.getCell(5), "开户行所在地", true);
        setCellText(headerRow1.getCell(6), "基本权限证书ID名称", true);

        // 第二行表头：新增/注销复选框行
        XWPFTableRow headerRow2 = table.getRow(1);
        setCellText(headerRow2.getCell(0), "新增□\n注销□", true);
        setCellText(headerRow2.getCell(1), "户名", true);
        setCellText(headerRow2.getCell(2), "", false);
        setCellText(headerRow2.getCell(3), "开户行名称", true);
        setCellText(headerRow2.getCell(4), "开户行号", true);
        setCellText(headerRow2.getCell(5), "开户行所在地", true);
        setCellText(headerRow2.getCell(6), "", false);

        // 填充数据行
        for (int i = 0; i < rowDataList.size(); i++) {
            XWPFTableRow dataRow = table.getRow(i + 2);
            AccountRowData rowData = rowDataList.get(i);

            // 业务类型 (如果是账号的第一行才显示)
            if (rowData.isFirstRow) {
                setCellText(dataRow.getCell(0), rowData.operationType, false);
            } else {
                setCellText(dataRow.getCell(0), "", false);
            }

            // 户名 (如果是账号的第一行才显示)
            if (rowData.isFirstRow && rowData.accountName != null) {
                setCellText(dataRow.getCell(1), "户名", true);
            } else {
                setCellText(dataRow.getCell(1), "", false);
            }

            // 账号 (如果是账号的第一行才显示)
            if (rowData.isFirstRow) {
                setCellText(dataRow.getCell(2), rowData.accountNo, false);
            } else {
                setCellText(dataRow.getCell(2), "", false);
            }

            // 开户行名称 (如果是账号的第一行才显示)
            if (rowData.isFirstRow) {
                setCellText(dataRow.getCell(3), rowData.openingBankName, false);
            } else {
                setCellText(dataRow.getCell(3), "", false);
            }

            // 开户行号 (如果是账号的第一行才显示)
            if (rowData.isFirstRow) {
                setCellText(dataRow.getCell(4), rowData.openingBankCode, false);
            } else {
                setCellText(dataRow.getCell(4), "", false);
            }

            // 开户行所在地 (如果是账号的第一行才显示)
            if (rowData.isFirstRow) {
                setCellText(dataRow.getCell(5), rowData.openingBankLocation, false);
            } else {
                setCellText(dataRow.getCell(5), "", false);
            }

            // 基本权限证书ID名称 (每行都显示)
            setCellText(dataRow.getCell(6), rowData.certIdName, false);
        }
    }

    /**
     * 准备账号行数据
     * 处理basePermissionCertIdName可能超过账号信息行数的情况
     */
    private static List<AccountRowData> prepareAccountRowData(List<ExtAccountItem> items) {
        List<AccountRowData> result = new ArrayList<>();

        for (ExtAccountItem item : items) {
            // 将basePermissionCertIdName按换行符或逗号分割
            String certIdNames = item.getBasePermissionCertIdName();
            if (certIdNames == null || certIdNames.trim().isEmpty()) {
                // 如果没有证书ID，至少创建一行
                AccountRowData rowData = new AccountRowData();
                rowData.isFirstRow = true;
                rowData.operationType = item.getOperationType() != null ? item.getOperationType().toString() : "";
                rowData.accountName = item.getAccountName();
                rowData.accountNo = item.getAccountNo();
                rowData.openingBankName = item.getOpeningBankName();
                rowData.openingBankCode = item.getOpeningBankCode();
                rowData.openingBankLocation = item.getOpeningBankLocation();
                rowData.certIdName = "";
                result.add(rowData);
            } else {
                // 分割证书ID名称
                String[] certIds = certIdNames.split("[,，\n]");
                for (int i = 0; i < certIds.length; i++) {
                    AccountRowData rowData = new AccountRowData();
                    rowData.isFirstRow = (i == 0);
                    rowData.operationType = item.getOperationType() != null ? item.getOperationType().toString() : "";
                    rowData.accountName = item.getAccountName();
                    rowData.accountNo = item.getAccountNo();
                    rowData.openingBankName = item.getOpeningBankName();
                    rowData.openingBankCode = item.getOpeningBankCode();
                    rowData.openingBankLocation = item.getOpeningBankLocation();
                    rowData.certIdName = certIds[i].trim();
                    result.add(rowData);
                }
            }
        }

        return result;
    }

    /**
     * 创建页脚信息
     */
    private static void createFooterInfo(XWPFDocument document) {
        XWPFParagraph para = document.createParagraph();
        XWPFRun run = para.createRun();
        run.setText("主申请账号银行行印鉴:                    填表日期:      年    月    日");
        run.setFontFamily("宋体");
        run.setFontSize(10);
    }

    /**
     * 创建填表说明
     */
    private static void createFormExplanation(XWPFDocument document) {
        XWPFParagraph para1 = document.createParagraph();
        XWPFRun run1 = para1.createRun();
        run1.setText("填表说明:");
        run1.setFontFamily("宋体");
        run1.setFontSize(10);
        run1.setBold(true);

        XWPFParagraph para2 = document.createParagraph();
        XWPFRun run2 = para2.createRun();
        String explanation = "1. 企业或集团外账户是指企业经常发生资金往来的其他企业或业的账户，" +
                "填写此表可以您在向这些企业或业订购时不必再填写对方账号、户名等资料。" +
                "企业或集团外币账户可以是开立在其他商业银行的账户。" +
                "在本表中所填写的企业或集团外账户在执行企业网上银行各项只能时为只能户使用。";
        run2.setText(explanation);
        run2.setFontFamily("宋体");
        run2.setFontSize(9);
    }

    /**
     * 设置单元格文本
     */
    private static void setCellText(XWPFTableCell cell, String text, boolean bold) {
        cell.removeParagraph(0);
        XWPFParagraph para = cell.addParagraph();
        para.setAlignment(ParagraphAlignment.CENTER);
        para.setVerticalAlignment(TextAlignment.CENTER);

        XWPFRun run = para.createRun();
        run.setText(text);
        run.setFontFamily("宋体");
        run.setFontSize(10);
        run.setBold(bold);

        // 设置单元格垂直居中
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
    }

    /**
     * 设置表格边框
     */
    private static void setTableBorders(XWPFTable table) {
        CTTblBorders borders = table.getCTTbl().getTblPr().addNewTblBorders();

        // 设置所有边框
        CTBorder border = CTBorder.Factory.newInstance();
        border.setVal(STBorder.SINGLE);
        border.setSz(BigInteger.valueOf(4));
        border.setSpace(BigInteger.ZERO);
        border.setColor("000000");

        borders.setTop(border);
        borders.setBottom(border);
        borders.setLeft(border);
        borders.setRight(border);
        borders.setInsideH(border);
        borders.setInsideV(border);
    }

    /**
     * 水平合并单元格
     */
    private static void mergeCellsHorizontally(XWPFTable table, int row, int fromCol, int toCol) {
        for (int colIndex = fromCol; colIndex <= toCol; colIndex++) {
            XWPFTableCell cell = table.getRow(row).getCell(colIndex);
            CTTcPr tcPr = cell.getCTTc().isSetTcPr() ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr();

            if (colIndex == fromCol) {
                // 第一个单元格设置为restart
                tcPr.addNewHMerge().setVal(STMerge.RESTART);
            } else {
                // 其他单元格设置为continue
                tcPr.addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }

    /**
     * 账号行数据内部类
     */
    private static class AccountRowData {
        boolean isFirstRow;
        String operationType;
        String accountName;
        String accountNo;
        String openingBankName;
        String openingBankCode;
        String openingBankLocation;
        String certIdName;
    }
}